export type RelationTreeNode<KeyT, T> = {
  id?: KeyT | undefined;
  parentId?: KeyT | undefined;
  parent?: T | undefined;
  children?: T[] | undefined;
};

export type SeparatorTreeNode<KeyT, T> = RelationTreeNode<KeyT, T> & {
  code?: string | undefined;
};

export function relationNodeArray2Tree<
  KeyT,
  T extends RelationTreeNode<KeyT, T>,
>(list: T[], callback?: (item: T) => void) {
  let map = new Map<KeyT, T>();

  // 清空已经存在的子元素，防止重复添加
  list.map((item) => {
    if (item.children != null) {
      item.children = [];
    }
    if (item.id) {
      map.set(item.id, item);
    }
  });

  // 构建父子关系
  for (var item of list) {
    // 无 parentId 的元素没有父级
    if (item.parentId == null) {
      continue;
    }
    let target = map.get(item.parentId);
    if (target) {
      target.children = target.children ?? [];
      target.children.push(item);
      item.parentId = target.id;
      item.parent = target;
    }
  }

  if (callback) {
    for (var item of list) {
      callback(item);
    }
  }

  // 返回根元素列表
  return list.filter((x) => !x.parentId);
}

export function separatorNodeArray2Tree<
  KeyT,
  T extends SeparatorTreeNode<KeyT, T>,
>(list: T[], separator: string) {
  let joiner = separator == "\\." ? "." : separator;
  let map = new Map<string, T>();

  // 清空已经存在的子元素，防止重复添加
  list.map((item) => {
    if (item.children != null) {
      item.children = [];
    }
    if (item.code) {
      map.set(item.code, item);
    }
  });

  // 构建父子关系
  for (var item of list) {
    if (item.code) {
      let codes = item.code.split(separator);
      // 无分割的元素没有父级
      if (codes.length == 1) {
        continue;
      }

      // 根据当前元素的 code 获取父级的 code
      codes = codes.slice(0, codes.length - 1);
      let parentCode = codes.join(joiner);
      let target = map.get(parentCode);
      if (target) {
        target.children = target.children ?? [];
        target.children.push(item);
        item.parentId = target.id;
        item.parent = target;
      }
    }
  }

  // 返回根元素列表
  return list.filter((x) => !x.parentId);
}

export function relationNodeTreeArray2Flat<
  KeyT,
  T extends RelationTreeNode<KeyT, T>,
>(treeList: T[]) {
  let flatArray: T[] = [];
  let loop = (array: T[], parent?: T) => {
    array.map((item) => {
      item.parent = parent;
      item.parentId = parent?.id;
      flatArray.push(item);
      if (!!item.children) {
        loop(item.children, item);
      }
    });
  };

  loop(treeList);
  return flatArray;
}

export function getRelationNodeTreeParents<
  KeyT,
  T extends RelationTreeNode<KeyT, T>,
>(flatList: T[], targetKey: KeyT) {
  let target: T | null = null;
  let parent: T | null;
  let parents: T[] = [];

  for (const item of flatList) {
    if (item.id == targetKey) {
      target = item;
      break;
    }
  }

  function loop(parentId: KeyT) {
    for (const item of flatList) {
      if (item.id == parentId) {
        parent = item;
        break;
      }
    }
    if (parent) {
      parents.push(parent);
      if (parent.parentId) {
        loop(parent.parentId);
      }
      parent = null;
    }
  }

  if (target?.parentId) {
    loop(target.parentId);
  }
  return parents.reverse();
}

export function callBackByChildren<KeyT, T extends RelationTreeNode<KeyT, T>>(
  treeList: T[],
  callback: (item: T) => void
) {
  for (var item of treeList) {
    callback && callback(item);
    if (!!item.children) {
      callBackByChildren(item.children, callback);
    }
  }
}
